home *** CD-ROM | disk | FTP | other *** search
/ Programming an RTS Game with Direct3D / Programming an RTS Game with Direct3D.iso / Examples / Chapter 5 / Example 5.9 / mouse.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2006-07-12  |  7.0 KB  |  275 lines

  1. #include "mouse.h"
  2.  
  3. //////////////////////////////////////////////////////////////////////////
  4. //                        RAY                                                //
  5. //////////////////////////////////////////////////////////////////////////
  6.  
  7. RAY::RAY()
  8. {
  9.     org = dir = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
  10. }
  11.  
  12. RAY::RAY(D3DXVECTOR3 o, D3DXVECTOR3 d)
  13. {
  14.     org = o;
  15.     dir = d;
  16. }
  17.  
  18. float RAY::Intersect(MESHINSTANCE iMesh)
  19. {
  20.     if(iMesh.m_pMesh == NULL)return -1.0f;
  21.     return Intersect(iMesh.m_pMesh->m_pMesh);
  22. }
  23.  
  24. float RAY::Intersect(BBOX bBox)
  25. {
  26.     if(D3DXBoxBoundProbe(&bBox.min, &bBox.max, &org, &dir))
  27.         return D3DXVec3Length(&(((bBox.min + bBox.max) / 2.0f) - org));
  28.     else return -1.0f;
  29. }
  30.  
  31. float RAY::Intersect(BSPHERE bSphere)
  32. {
  33.     if(D3DXSphereBoundProbe(&bSphere.center, bSphere.radius, &org, &dir))
  34.         return D3DXVec3Length(&(bSphere.center - org));
  35.     else return -1.0f;
  36. }
  37.  
  38. float RAY::Intersect(ID3DXMesh* mesh)
  39. {
  40.     if(mesh == NULL)return -1.0f;
  41.  
  42.     // Collect only the closest intersection
  43.     BOOL hit;
  44.     DWORD dwFace;
  45.     float hitU, hitV, dist;
  46.     D3DXIntersect(mesh, &org, &dir, &hit, &dwFace, &hitU, &hitV, &dist, NULL, NULL);
  47.  
  48.     if(hit) return dist;
  49.     else return -1.0f;
  50. }
  51.  
  52. //////////////////////////////////////////////////////////////////////////
  53. //                        MOUSE                                            //
  54. //////////////////////////////////////////////////////////////////////////
  55.  
  56. MOUSE::MOUSE()
  57. {
  58.     m_type = 0;
  59.     m_pMouseTexture = NULL;
  60.     m_pMouseDevice = NULL;
  61.     m_speed = 1.5f;
  62. }
  63.  
  64. MOUSE::~MOUSE()
  65. {
  66.     if(m_pMouseDevice != NULL)
  67.         m_pMouseDevice->Release();
  68.  
  69.     if(m_pMouseTexture != NULL)
  70.         m_pMouseTexture->Release();
  71. }
  72.  
  73. void MOUSE::InitMouse(IDirect3DDevice9* Dev, HWND wnd)
  74. {
  75.     try
  76.     {
  77.         m_pDevice = Dev;
  78.  
  79.         //Load texture and init sprite
  80.         D3DXCreateTextureFromFile(m_pDevice, "cursor/cursor.dds", &m_pMouseTexture);
  81.         D3DXCreateSprite(m_pDevice, &m_pSprite);
  82.  
  83.         //Get directinput object
  84.         LPDIRECTINPUT8 directInput = NULL;
  85.  
  86.         DirectInput8Create(GetModuleHandle(NULL),    // Retrieves the application handle
  87.                            0x0800,                    // v.8.0    
  88.                            IID_IDirectInput8,        // Interface ID
  89.                            (VOID**)&directInput,    // Our DirectInput Object
  90.                            NULL);
  91.  
  92.         //Acquire Default System mouse
  93.         directInput->CreateDevice(GUID_SysMouse, &m_pMouseDevice, NULL);        
  94.         m_pMouseDevice->SetDataFormat(&c_dfDIMouse);
  95.         m_pMouseDevice->SetCooperativeLevel(wnd, DISCL_EXCLUSIVE | DISCL_FOREGROUND);
  96.         m_pMouseDevice->Acquire();            
  97.  
  98.         //Get m_viewport size and init mouse location
  99.         D3DVIEWPORT9 v;
  100.         m_pDevice->GetViewport(&v);
  101.         m_viewport.left = v.X;
  102.         m_viewport.top = v.Y;
  103.         m_viewport.right = v.X + v.Width;
  104.         m_viewport.bottom = v.Y + v.Height;
  105.  
  106.         x = v.X + v.Width / 2.0f;
  107.         y = v.Y + v.Height / 2.0f;
  108.  
  109.         //Release Direct Input Object
  110.         directInput->Release();
  111.  
  112.         //Create Mouse Sphere
  113.         D3DXCreateSphere(m_pDevice, 0.2f, 5, 5, &m_pSphereMesh, NULL);
  114.  
  115.         //Create Ball Material
  116.         m_ballMtrl.Diffuse = D3DXCOLOR(1.0f, 1.0f, 0.0f, 1.0f);
  117.         m_ballMtrl.Specular = m_ballMtrl.Ambient = m_ballMtrl.Emissive = D3DXCOLOR(0.0f, 0.0f, 0.0f, 1.0f);
  118.     }
  119.     catch(...)
  120.     {
  121.         debug.Print("Error in MOUSE::InitMouse()");
  122.     }    
  123. }
  124.  
  125. bool MOUSE::ClickLeft()
  126.     return m_mouseState.rgbButtons[0];
  127. }
  128.  
  129. bool MOUSE::ClickRight()
  130. {
  131.     return m_mouseState.rgbButtons[1];
  132. }
  133.  
  134. bool MOUSE::WheelUp()
  135. {
  136.     return m_mouseState.lZ > 0.0f;
  137. }
  138.  
  139. bool MOUSE::WheelDown()
  140. {
  141.     return m_mouseState.lZ < 0.0f;
  142. }
  143.  
  144. bool MOUSE::Over(RECT dest)
  145. {
  146.     if(x < dest.left || x > dest.right)return false;
  147.     if(y < dest.top || y > dest.bottom)return false;
  148.     return true;
  149. }
  150.  
  151. bool MOUSE::PressInRect(RECT dest)
  152. {
  153.     return ClickLeft() && Over(dest);
  154. }
  155.  
  156. void MOUSE::Update(TERRAIN &terrain)
  157. {
  158.     //Retrieve mouse state
  159.     ZeroMemory(&m_mouseState, sizeof(DIMOUSESTATE));
  160.     m_pMouseDevice->GetDeviceState(sizeof(DIMOUSESTATE), &m_mouseState);
  161.  
  162.     //Update pointer
  163.     x += m_mouseState.lX * m_speed;
  164.     y += m_mouseState.lY * m_speed;
  165.  
  166.     //Keep mouse pointer within window
  167.     if(x < m_viewport.left)    x = m_viewport.left;
  168.     if(y < m_viewport.top)    y = m_viewport.top;
  169.     if(x > m_viewport.right)    x = m_viewport.right;
  170.     if(y > m_viewport.bottom)    y = m_viewport.bottom;
  171.  
  172.     CalculateMappos(terrain);
  173. }
  174.  
  175. void MOUSE::Paint()
  176. {    
  177.     //Draw ball
  178.     D3DXMATRIX world;
  179.     D3DXMatrixTranslation(&world, m_ballPos.x, m_ballPos.y, m_ballPos.z);
  180.     m_pDevice->SetTransform(D3DTS_WORLD, &world);
  181.     m_pDevice->SetMaterial(&m_ballMtrl);
  182.     m_pDevice->SetTexture(0, NULL);
  183.     m_pSphereMesh->DrawSubset(0);
  184.  
  185.     if(m_pMouseTexture != NULL)
  186.     {
  187.         RECT src[] = {{0,0,20,20}, {0,20,20,40}, {20,20,40,40}, {0,40,20,60}, {20,40,40,60}};
  188.  
  189.         m_pSprite->Begin(D3DXSPRITE_ALPHABLEND);
  190.         m_pSprite->Draw(m_pMouseTexture, &src[m_type], NULL, &D3DXVECTOR3(x, y, 0.0f), 0xffffffff);
  191.         m_pSprite->End();
  192.     }    
  193. }
  194.  
  195. RAY MOUSE::GetRay()
  196. {
  197.     try
  198.     {
  199.         D3DXMATRIX projectionMatrix, viewMatrix, worldViewInverse, worldMatrix;
  200.         
  201.         m_pDevice->GetTransform(D3DTS_PROJECTION, &projectionMatrix);
  202.         m_pDevice->GetTransform(D3DTS_VIEW, &viewMatrix);
  203.         m_pDevice->GetTransform(D3DTS_WORLD, &worldMatrix);
  204.  
  205.         float width = m_viewport.right - m_viewport.left;
  206.         float height = m_viewport.bottom - m_viewport.top;
  207.  
  208.         float angle_x = (((2.0f * x) / width) - 1.0f) / projectionMatrix(0,0);
  209.         float angle_y = (((-2.0f * y) / height) + 1.0f) / projectionMatrix(1,1); 
  210.         
  211.         RAY ray;
  212.         ray.org = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
  213.         ray.dir = D3DXVECTOR3(angle_x, angle_y, 1.0f);
  214.  
  215.         D3DXMATRIX m = worldMatrix * viewMatrix;
  216.         D3DXMatrixInverse(&worldViewInverse, 0, &m);
  217.         D3DXVec3TransformCoord(&ray.org, &ray.org, &worldViewInverse);
  218.         D3DXVec3TransformNormal(&ray.dir, &ray.dir, &worldViewInverse);
  219.         D3DXVec3Normalize(&ray.dir, &ray.dir);
  220.  
  221.         return ray;
  222.     }
  223.     catch(...)
  224.     {
  225.         debug.Print("Error in MOUSE::GetRay()");
  226.     }
  227. }
  228.  
  229. void MOUSE::CalculateMappos(TERRAIN &terrain)
  230. {
  231.     //Get Mouse Ray
  232.     D3DXMATRIX world;
  233.     D3DXMatrixIdentity(&world);
  234.     m_pDevice->SetTransform(D3DTS_WORLD, &world);
  235.     RAY mRay = GetRay();
  236.  
  237.     float minDistance = 10000.0f;
  238.     for(int i=0;i<terrain.m_patches.size();i++)
  239.     {
  240.         if(mRay.Intersect(terrain.m_patches[i]->m_BBox) > 0.0f)
  241.         {
  242.             // Collect only the closest intersection
  243.             BOOL hit;
  244.             DWORD dwFace;
  245.             float hitU, hitV, dist;
  246.             D3DXIntersect(terrain.m_patches[i]->m_pMesh, &mRay.org, &mRay.dir, &hit, &dwFace, &hitU, &hitV, &dist, NULL, NULL);
  247.  
  248.             if(hit && dist < minDistance)
  249.             {
  250.                 minDistance = dist;
  251.                 int tiles = dwFace / 2;        //Two faces to each map tile
  252.                 int tilesPerRow = terrain.m_patches[i]->m_mapRect.right - terrain.m_patches[i]->m_mapRect.left;
  253.                 int y = tiles / tilesPerRow, x = tiles - y * tilesPerRow;
  254.  
  255.                 if(dwFace % 2 == 0)        //Hit upper left face
  256.                 {
  257.                     if(hitU > 0.5f)x++;
  258.                     else if(hitV > 0.5f)y++;
  259.                 }
  260.                 else                    //Hit lower right face
  261.                 {
  262.                     if(hitU + hitV < 0.5f)y++;
  263.                     else if(hitU > 0.5f)x++;
  264.                     else {x++;y++;}
  265.                 }
  266.  
  267.                 //Set mouse map position
  268.                 m_mappos.Set(terrain.m_patches[i]->m_mapRect.left + x, terrain.m_patches[i]->m_mapRect.top + y);
  269.                 m_ballPos = terrain.GetWorldPos(m_mappos);
  270.                 m_uv = D3DXVECTOR2(hitU, hitV);
  271.             }            
  272.         }
  273.     }    
  274. }